babl-conversion.c \
babl-extension.c \
babl-fish.c \
+ babl-fish-simple.c \
+ babl-fish-reference.c \
+ babl-fish-path.c \
babl-format.c \
babl-image.c \
babl-internal.c \
#include "babl-db.h"
#include <string.h>
#include <stdarg.h>
+#include <math.h>
static int
each_babl_conversion_destroy (Babl *babl,
void *data)
{
- babl_free (babl->instance.name);
babl_free (babl);
return 0; /* continue iterating */
}
babl_assert (source->class_type ==
destination->class_type);
+ babl = babl_malloc (sizeof (BablConversion) + strlen (name) + 1);
+ babl->instance.name = (void *)babl + sizeof (BablConversion);
+ strcpy(babl->instance.name, name);
+
if (linear)
{
- babl = babl_malloc (sizeof (BablConversion));
babl->class_type = BABL_CONVERSION_LINEAR;
babl->conversion.function.linear = linear;
}
else if (plane)
{
- babl = babl_malloc (sizeof (BablConversion));
babl->class_type = BABL_CONVERSION_PLANE;
babl->conversion.function.plane = plane;
}
else if (planar)
{
- babl = babl_malloc (sizeof (BablConversion));
babl->class_type = BABL_CONVERSION_PLANAR;
babl->conversion.function.planar = planar;
}
switch (source->class_type)
{
case BABL_TYPE:
- break;
- case BABL_MODEL:
- if (linear)
+ if (linear) /* maybe linear could take a special argument, passed as an
+ additional key/value pair in the constructor. To cast it
+ as a generic N-element conversion, thus making it applicable
+ to being generic for any within model conversion of plain
+ buffers.
+ */
{
- babl_fatal ("linear support for %s not supported",
+ babl_fatal ("linear conversions not supported for %s",
babl_class_name (source->class_type));
}
- else if (plane)
+ else if (planar)
{
- babl_fatal ("plane support for %s not supported",
+ babl_fatal ("planar conversions not supported for %ssupported",
+ babl_class_name (source->class_type));
+ }
+ break;
+ case BABL_MODEL:
+ if (plane)
+ {
+ babl_fatal ("plane conversions not supported for %s",
babl_class_name (source->class_type));
}
break;
}
babl->instance.id = id;
- babl->instance.name = babl_strdup (name);
babl->conversion.source = (union Babl*)source;
babl->conversion.destination = (union Babl*)destination;
- babl->conversion.error = 0.0;
+ babl->conversion.error = -1.0;
+ babl->conversion.cost = 69;
babl->conversion.pixels = 0;
babl->conversion.processings = 0;
- babl_add_ptr_to_list ((void ***)&(source->type.from), babl);
-
+ if (babl->class_type == BABL_CONVERSION_LINEAR &&
+ BABL(babl->conversion.source)->class_type == BABL_MODEL)
+ {
+ Babl *src_format=NULL;
+ Babl *dst_format=NULL;
+ if (BABL(babl->conversion.source) == babl_model_id (BABL_RGBA))
+ {
+ src_format = babl_format_id (BABL_RGBA_DOUBLE);
+ dst_format = babl_format_with_model_as_type (
+ BABL(babl->conversion.destination),
+ babl_type_id (BABL_DOUBLE));
+ }
+ else if (BABL(babl->conversion.destination) == babl_model_id (BABL_RGBA))
+ {
+ src_format = babl_format_with_model_as_type (
+ BABL(babl->conversion.source),
+ babl_type_id (BABL_DOUBLE));
+ dst_format = babl_format_id (BABL_RGBA_DOUBLE);
+ }
+ else
+ {
+ babl_fatal ("neither source nor destination model is RGBA (requirement might be temporary)");
+ }
+ babl_conversion_new (
+ src_format,
+ dst_format,
+ "linear", linear,
+ NULL);
+ babl->conversion.error = 0.0;
+ }
+
return babl;
}
static char buf[512]="";
static char *
-create_name (Babl *source, Babl *destination)
+create_name (Babl *source, Babl *destination, int type)
{
if (babl_extender ())
{
- snprintf (buf, 512-1, "%s : %s to %s", BABL(babl_extender())->instance.name, source->instance.name, destination->instance.name);
+ snprintf (buf, 512-1, "%s : %s%s to %s",
+ BABL(babl_extender())->instance.name,
+ type == BABL_CONVERSION_LINEAR?"":
+ type == BABL_CONVERSION_PLANE?"plane ":
+ type == BABL_CONVERSION_PLANAR?"planar ":"Eeeek! ",
+ source->instance.name,
+ destination->instance.name);
buf[511]='\0';
}
else
{
- snprintf (buf, 512-1, "%s to %s", source->instance.name, destination->instance.name);
+ snprintf (buf, 512-1, "%s %s to %s",
+ type == BABL_CONVERSION_LINEAR?"":
+ type == BABL_CONVERSION_PLANE?"plane ":
+ type == BABL_CONVERSION_PLANAR?"planar ":"Eeeek! ",
+ source->instance.name,
+ destination->instance.name);
buf[511]='\0';
}
return buf;
BablFuncLinear linear = NULL;
BablFuncPlane plane = NULL;
BablFuncPlanar planar = NULL;
-
+ int type = 0;
int got_func = 0;
const char *arg = first_arg;
assert (BABL_IS_BABL(source));
assert (BABL_IS_BABL(destination));
+
while (arg)
{
assert (source);
assert (destination);
- babl = conversion_new (create_name (source, destination),
+ if (linear)
+ {
+ type = BABL_CONVERSION_LINEAR;
+ }
+ else if (plane)
+ {
+ type = BABL_CONVERSION_PLANE;
+ }
+ else if (planar)
+ {
+ type = BABL_CONVERSION_PLANAR;
+ }
+ babl = conversion_new (create_name (source, destination, type),
id, source, destination, linear, plane, planar);
{
Babl *ret = babl_db_insert (db, babl);
if (ret!=babl)
babl_free (babl);
+ else
+ babl_add_ptr_to_list ((void ***)&(source->type.from), babl);
+
return ret;
}
}
}
long
-babl_conversion_process (BablConversion *conversion,
- void *source,
- void *destination,
- long n)
+babl_conversion_process (Babl *babl,
+ void *source,
+ void *destination,
+ long n)
{
+ BablConversion *conversion = (BablConversion*) babl;
+
babl_assert (BABL_IS_BABL (conversion));
switch (BABL(conversion)->class_type)
n);
break;
case BABL_CONVERSION_LINEAR:
- babl_assert (!BABL_IS_BABL (source));
- babl_assert (!BABL_IS_BABL (destination));
+ /* the assertions relied on a babl_malloc structure
+ *
+ * babl_assert (!BABL_IS_BABL (source));
+ babl_assert (!BABL_IS_BABL (destination));*/
babl_conversion_linear_process (conversion,
source,
return 0;
break;
}
+
+ conversion->processings ++;
+ conversion->pixels += n;
return n;
}
+#define pixels 8192*2
+
+static double *
+test_create (void)
+{
+ double *test;
+ int i;
+
+ srandom (20050728);
+
+ test = babl_malloc (sizeof (double) * pixels * 4);
+
+ for (i = 0; i < pixels * 4; i++)
+ test [i] = (double) random () / RAND_MAX;
+
+ return test;
+}
+
+double
+babl_conversion_error (BablConversion *conversion)
+{
+ Babl *fmt_source;
+ Babl *fmt_destination;
+
+ Babl *fmt_rgba_double;
+
+ double error = 0.0;
+ unsigned int ticks_start = 0;
+ unsigned int ticks_end = 0;
+
+ double *test;
+ void *source;
+ void *destination;
+ double *destination_rgba_double;
+ void *ref_destination;
+ double *ref_destination_rgba_double;
+
+
+ if (!conversion)
+ return 0.0;
+
+ fmt_source = BABL(conversion->source);
+ fmt_destination = BABL(conversion->destination);
+
+ if (fmt_source == fmt_destination)
+ {
+ conversion->error = 0.0;
+ return 0.0;
+ }
+
+ if (!(fmt_source->instance.id != BABL_RGBA &&
+ fmt_destination->instance.id != BABL_RGBA &&
+ fmt_source->instance.id != BABL_DOUBLE &&
+ fmt_destination->instance.id != BABL_DOUBLE &&
+ fmt_source->class_type == BABL_FORMAT &&
+ fmt_destination->class_type == BABL_FORMAT))
+ {
+ conversion->error = 0.000042;
+ }
+ if (conversion->error != -1.0) /* double conversion against a set value should work */
+ {
+ return conversion->error;
+ }
+
+ test=test_create ();
+
+ fmt_rgba_double = babl_format_new (
+ babl_model ("RGBA"),
+ babl_type ("double"),
+ babl_component ("R"),
+ babl_component ("G"),
+ babl_component ("B"),
+ babl_component ("A"),
+ NULL);
+
+
+ source = babl_calloc (pixels, fmt_source->format.bytes_per_pixel);
+ destination = babl_calloc (pixels, fmt_destination->format.bytes_per_pixel);
+ ref_destination = babl_calloc (pixels, fmt_destination->format.bytes_per_pixel);
+ destination_rgba_double = babl_calloc (pixels, fmt_rgba_double->format.bytes_per_pixel);
+ ref_destination_rgba_double = babl_calloc (pixels, fmt_rgba_double->format.bytes_per_pixel);
+
+ babl_process (babl_fish_reference (fmt_rgba_double, fmt_source),
+ test, source, pixels);
+
+ ticks_start = babl_ticks ();
+ babl_process (babl_fish_simple (conversion),
+ source, destination, pixels);
+ ticks_end = babl_ticks ();
+
+ babl_process (babl_fish_reference (fmt_source, fmt_destination),
+ source, ref_destination, pixels);
+
+ babl_process (babl_fish_reference (fmt_destination, fmt_rgba_double),
+ ref_destination, ref_destination_rgba_double, pixels);
+ babl_process (babl_fish_reference (fmt_destination, fmt_rgba_double),
+ destination, destination_rgba_double, pixels);
+
+ {
+ int i;
+
+ for (i=0;i<pixels;i++)
+ {
+ int j;
+ for (j=0;j<4;j++)
+ error += fabs (destination_rgba_double[i*4+j] -
+ ref_destination_rgba_double[i*4+j]);
+ }
+ error /= pixels;
+ error *= 100;
+ }
+
+ babl_free (source);
+ babl_free (destination);
+ babl_free (destination_rgba_double);
+ babl_free (ref_destination);
+ babl_free (ref_destination_rgba_double);
+ babl_free (test);
+
+ conversion->error = error;
+ conversion->cost = ticks_end-ticks_start;
+
+ return error;
+}
+
+
BABL_CLASS_TEMPLATE (conversion)
return n;
}
+/*
static long
copy_strip_1 (int src_bands,
void **src,
return n;
}
+
+*/
+static long
+rgba_to_rgba (void *src,
+ void *dst,
+ long n)
+{
+ memcpy (dst, src, n * sizeof (double) * 4);
+ return n;
+}
void
babl_core_init (void)
{
"bits", 64,
NULL);
- babl_conversion_new (
- babl_type_id (BABL_DOUBLE),
- babl_type_id (BABL_DOUBLE),
- "plane", convert_double_double,
- NULL
- );
-
babl_component_new (
"R",
"id", BABL_RED,
babl_component_id (BABL_ALPHA),
NULL);
+ babl_format_new (
+ "id", BABL_RGBA_DOUBLE,
+ babl_model_id (BABL_RGBA),
+ babl_type_id (BABL_DOUBLE),
+ babl_component_id (BABL_RED),
+ babl_component_id (BABL_GREEN),
+ babl_component_id (BABL_BLUE),
+ babl_component_id (BABL_ALPHA),
+ NULL);
+
+ /*
babl_conversion_new (
babl_model_id (BABL_RGBA),
babl_model_id (BABL_RGBA),
"planar", copy_strip_1,
NULL
);
+ */
+
+ babl_conversion_new (
+ babl_type_id (BABL_DOUBLE),
+ babl_type_id (BABL_DOUBLE),
+ "plane", convert_double_double,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_model_id (BABL_RGBA),
+ babl_model_id (BABL_RGBA),
+ "linear", rgba_to_rgba,
+ NULL
+ );
}
return db;
}
+
+int
+babl_db_count (BablDb *db)
+{
+ return db->count;
+}
+
void
babl_db_destroy (BablDb *db)
{
void babl_db_each (BablDb *db,
BablEachFunction each_fun,
void *user_data);
+int babl_db_count (BablDb *db);
Babl * babl_db_insert (BablDb *db,
Babl *entry);
Babl * babl_db_exist (BablDb *db,
--- /dev/null
+/* babl - dynamically extendable universal pixel fish library.
+ * Copyright (C) 2005, Øyvind Kolås.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "babl-internal.h"
+
+#define BABL_LEGAL_ERROR 0.000001
+
+typedef struct BablChainContext {
+ Babl *from;
+ Babl *to;
+
+ double *best_cost;
+ double *best_loss;
+
+ Babl **chain;
+ int *conversions;
+
+ Babl **temp_chain;
+ int temp_conversions;
+
+ int max_conversions;
+} BablChainContext;
+
+static int
+format_has_alpha (Babl *babl)
+{
+ int i;
+ for (i=0; i<babl->format.components; i++)
+ if (babl->format.component[i]->instance.id == BABL_ALPHA)
+ return 1;
+ return 0;
+}
+
+static int
+format_analytic_loss (Babl *source,
+ Babl *destination)
+{
+ int loss = 0;
+
+ if (source->format.components <
+ destination->format.components)
+ {
+ loss |= 8;
+ }
+
+ if ( format_has_alpha (source) &&
+ !format_has_alpha (destination))
+ {
+ loss |= 4;
+ }
+
+ if ( BABL(source->format.type[0])->type.bits >
+ BABL(destination->format.type[0])->type.bits)
+ {
+ loss |= 2;
+ }
+
+ if ( source->format.bytes_per_pixel >
+ destination->format.bytes_per_pixel)
+ {
+ loss |= 1;
+ }
+
+
+
+
+ return loss;
+}
+
+
+static int
+chain_gen_each (Babl *babl,
+ void *userdata);
+
+static int
+get_conversion_chain (Babl *from,
+ Babl *to,
+
+ double *best_cost,
+ double *best_loss,
+ Babl **chain,
+ int *conversions,
+
+ Babl **temp_chain,
+ int temp_conversions,
+
+ int max_conversions)
+{
+ BablChainContext context;
+
+ if (temp_conversions>=max_conversions)
+ return 0;
+
+ if (temp_conversions == 0)
+ {
+ /* chain initialization */
+ *conversions = 0;
+ *best_cost = 200000.0;
+ *best_loss = 200000.0;
+ chain[0] = NULL;
+ temp_chain[0] = NULL;
+
+ /* Bail out if requesting something stupid (to and from same format, an
+ * optimized memcpy should be used instead (assuming linear buffers).
+ */
+
+ if (from == to)
+ return 0;
+ }
+
+ /* copy parameters to stack */
+ context.from = from;
+ context.to = to;
+
+ context.best_cost = best_cost;
+ context.best_loss = best_loss;
+ context.chain = chain;
+ context.conversions = conversions;
+
+ context.temp_chain = temp_chain;
+ context.temp_conversions = temp_conversions;
+
+ context.max_conversions = max_conversions;
+
+ if (temp_conversions == 0)
+ {
+ temp_chain[temp_conversions]=NULL;
+ babl_assert (from);
+ babl_assert (from->class_type == BABL_FORMAT);
+ if (!from->format.from)
+ return 0;
+
+ babl_list_each ((void**) from->format.from,
+ chain_gen_each,
+ &context);
+ }
+ else
+ {
+ if (BABL(temp_chain[temp_conversions-1]) &&
+ BABL(temp_chain[temp_conversions-1]->conversion.destination)->
+ format.from)
+
+ babl_list_each (
+ (void **)
+ BABL(temp_chain[temp_conversions-1]->conversion.destination)->
+ format.from,
+ chain_gen_each,
+ &context);
+ }
+
+ return 0;
+}
+
+static int
+chain_gen_each (Babl *babl,
+ void *userdata)
+{
+ BablChainContext *c = userdata;
+
+ /* fill in the conversion for the chain index we are at */
+ c->temp_chain[c->temp_conversions] = babl;
+
+ {
+ if (BABL(babl->conversion.destination) == c->to)
+ {
+ /* a candidate path has been found */
+
+ double temp_cost = 0.0;
+ double temp_loss = 0.0;
+ double error = 1.0;
+ int analytic_loss = 0;
+ int i;
+
+ for (i=0; i < c->temp_conversions+1; i++)
+ {
+ error *= (1.0+c->temp_chain[i]->conversion.error);
+ temp_cost += c->temp_chain[i]->conversion.cost;
+ analytic_loss |= format_analytic_loss (
+ BABL(c->temp_chain[i]->conversion.source),
+ BABL(c->temp_chain[i]->conversion.destination));
+ }
+ temp_loss = analytic_loss;
+
+ if (error <= (1.0 + BABL_LEGAL_ERROR) /* we're legal */ &&
+
+ /* better than the existing best candidate */
+ ( temp_loss < *c->best_loss ||
+ (temp_loss == *c->best_loss &&
+ temp_cost < *c->best_cost)))
+ {
+ int i;
+
+ *c->best_cost = temp_cost;
+ *c->best_loss = temp_loss;
+ *c->conversions = c->temp_conversions + 1;
+
+ /* copy from temp chain to best chain */
+ for (i = 0.0; i < *c->conversions; i++)
+ c->chain[i] = c->temp_chain[i];
+ }
+ }
+ else
+ {
+ /* try to add another conversion level in chain,.. */
+ get_conversion_chain (c->from, /* irrelevant when recalled */
+ c->to,
+
+ c->best_cost,
+ c->best_loss,
+ c->chain,
+ c->conversions,
+
+ c->temp_chain,
+ c->temp_conversions + 1,
+
+ c->max_conversions);
+ }
+ }
+ return 0;
+}
+
+static inline Babl *
+assert_conversion_find (void *source,
+ void *destination)
+{
+ int i=0;
+ Babl **conversion;
+
+ conversion = (void*)BABL(source)->type.from;
+ while (conversion && conversion[i])
+ {
+ if (conversion[i]->conversion.destination == destination)
+ return (Babl*)conversion[i];
+ i++;
+ }
+ babl_fatal ("failed, aborting");
+ return NULL;
+}
+
+static char buf[1024];
+static char *
+create_name (Babl *source,
+ Babl *destination,
+ int is_reference)
+{
+ /* fish names are intentionally kept short */
+ snprintf (buf, 1024, "%s %p %p", "",
+ source, destination);
+ return buf;
+}
+
+Babl *
+babl_fish_path (Babl *source,
+ Babl *destination)
+{
+ Babl *babl = NULL;
+ char *name = create_name (source, destination, 1);
+ Babl *temp_chain[BABL_MAX_PATH_LENGTH];
+
+ babl_assert (BABL_IS_BABL (source));
+ babl_assert (BABL_IS_BABL (destination));
+
+ babl_assert (source->class_type == BABL_FORMAT);
+ babl_assert (destination->class_type == BABL_FORMAT);
+
+ babl = babl_calloc (1, sizeof (BablFishPath) +
+ strlen (name) + 1);
+ babl->class_type = BABL_FISH_PATH;
+ babl->instance.id = 0;
+ babl->instance.name = ((void *)babl) + sizeof(BablFishPath);
+ strcpy (babl->instance.name, name);
+ babl->fish.source = (union Babl*)source;
+ babl->fish.destination = (union Babl*)destination;
+
+ babl->fish.processings = 0;
+ babl->fish.pixels = 0;
+
+ babl->fish_path.cost = 200000;
+ babl->fish_path.loss = 200000;
+ babl->fish_path.conversions = 0;
+ babl->fish_path.conversion[0] = NULL;
+
+ babl_assert (source->class_type == BABL_FORMAT);
+ babl_assert (destination->class_type == BABL_FORMAT);
+
+ get_conversion_chain (source,
+ destination,
+ &babl->fish_path.cost,
+ &babl->fish_path.loss,
+ (Babl**)(babl->fish_path.conversion),
+ &babl->fish_path.conversions,
+ temp_chain,
+ 0,
+ BABL_MAX_PATH_LENGTH);
+ if (babl->fish_path.conversions==0)
+ {
+ babl_free (babl);
+ return NULL;
+ }
+
+ {
+ Babl *ret = babl_db_insert (babl_fish_db (), babl);
+ if (ret!=babl)
+ babl_free (babl);
+ return ret;
+ }
+}
+
+static long
+chain_process (BablConversion *chain[],
+ int conversions,
+ void *source,
+ void *destination,
+ long n)
+{
+ void *bufA = NULL;
+ void *bufB = NULL;
+ int i;
+
+ babl_assert (source);
+ babl_assert (destination);
+
+ if (conversions > 1)
+ bufA = babl_malloc (n * sizeof (double) * 5);
+ if (conversions > 2)
+ bufB = babl_malloc (n * sizeof (double) * 5);
+
+ for (i=0; i<conversions; i++)
+ {
+ if (i==0 && conversions == i+1)
+ {
+ babl_conversion_process ( BABL(chain[i]),
+ source, destination, n);
+ }
+ else if (i == 0)
+ {
+ babl_conversion_process ( BABL(chain[i]),
+ source, bufA, n);
+ }
+ else if (i % 2 == 1)
+ {
+ if (i + 1 == conversions)
+ {
+ babl_conversion_process ( BABL(chain[i]),
+ bufA, destination, n);
+ }
+ else
+ {
+ babl_conversion_process ( BABL(chain[i]),
+ bufA, bufB, n);
+ }
+ }
+ else if (i % 2 == 0)
+ {
+ if (i + 1 == conversions)
+ {
+ babl_conversion_process ( BABL(chain[i]),
+ bufB, destination, n);
+ }
+ else
+ {
+ babl_conversion_process ( BABL(chain[i]),
+ bufB, bufA, n);
+ }
+ }
+ i ++;
+ }
+ if (bufA)
+ babl_free (bufA);
+ if (bufB)
+ babl_free (bufB);
+
+ return n;
+}
+
+long
+babl_fish_path_process (Babl *babl,
+ void *source,
+ void *destination,
+ long n)
+{
+ /*
+ int i;
+ */
+
+ babl_assert (source);
+ babl_assert (destination);
+/*
+ babl_log ("path processing from %s to %s",
+ BABL(babl->fish.source)->instance.name,
+ BABL(babl->fish.destination)->instance.name);
+
+ for (i=0; i< babl->fish_path.conversions; i++)
+ babl_log ("\t%s\n",
+ BABL(babl->fish_path.conversion[i])->instance.name);
+*/
+
+ return chain_process (babl->fish_path.conversion,
+ babl->fish_path.conversions,
+ source,
+ destination,
+ n);
+}
+
--- /dev/null
+/* babl - dynamically extendable universal pixel fish library.
+ * Copyright (C) 2005, Øyvind Kolås.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "babl-internal.h"
+
+static Babl *
+assert_conversion_find (void *source,
+ void *destination)
+{
+ Babl *ret = babl_conversion_find (source, destination);
+
+ if (!ret)
+ babl_fatal ("failed, aborting");
+ return ret;
+}
+
+static char buf[1024];
+static char *
+create_name (Babl *source,
+ Babl *destination,
+ int is_reference)
+{
+ /* fish names are intentionally kept short */
+ snprintf (buf, 1024, "%s %p %p",
+ is_reference?"ref "
+ :"",
+ source, destination);
+ return buf;
+}
+
+
+Babl *
+babl_fish_reference (Babl *source,
+ Babl *destination)
+{
+ Babl *babl = NULL;
+ char *name = create_name (source, destination, 1);
+
+ babl_assert (BABL_IS_BABL (source));
+ babl_assert (BABL_IS_BABL (destination));
+
+ babl_assert (source->class_type == BABL_FORMAT);
+ babl_assert (destination->class_type == BABL_FORMAT);
+
+ babl = babl_malloc (sizeof (BablFishReference) +
+ strlen (name) + 1);
+ babl->class_type = BABL_FISH_REFERENCE;
+ babl->instance.id = 0;
+ babl->instance.name = ((void *)babl) + sizeof(BablFishReference);
+ strcpy (babl->instance.name, name);
+ babl->fish.source = (union Babl*)source;
+ babl->fish.destination = (union Babl*)destination;
+
+ babl->fish.processings = 0;
+ babl->fish.pixels = 0;
+
+ {
+ Babl *ret = babl_db_insert (babl_fish_db (), babl);
+ if (ret!=babl)
+ babl_free (babl);
+ return ret;
+ }
+}
+
+
+static void
+convert_to_double (BablFormat *source_fmt,
+ BablImage *source,
+ void *source_buf,
+ void *source_double_buf,
+ int n)
+{
+ int i;
+
+ BablImage *src_img;
+ BablImage *dst_img;
+
+ src_img = (BablImage*) babl_image (
+ babl_component_id (BABL_LUMINANCE), NULL, 1, 0, NULL);
+ dst_img = (BablImage*) babl_image (
+ babl_component_id (BABL_LUMINANCE), NULL, 1, 0, NULL);
+
+ dst_img->type[0] = (BablType*) babl_type_id (BABL_DOUBLE);
+ dst_img->pitch[0] =
+ (dst_img->type[0]->bits/8) * source_fmt->model->components;
+ dst_img->stride[0] = 0;
+
+
+ src_img->data[0] = source_buf;
+ src_img->type[0] = (BablType*) babl_type_id (BABL_DOUBLE);
+ src_img->pitch[0] = source_fmt->bytes_per_pixel;
+ src_img->stride[0] = 0;
+
+ /* i is source position */
+ for (i=0 ; i<source_fmt->components; i++)
+ {
+ int j;
+
+ src_img->type[0] = source_fmt->type[i];
+ /* j is source position */
+ for (j=0;j<source_fmt->model->components;j++)
+ {
+ if (source_fmt->component[i] ==
+ source_fmt->model->component[j])
+ {
+ dst_img->data[0] =
+ source_double_buf + (dst_img->type[0]->bits/8) * j;
+ break;
+ }
+ }
+
+ babl_process (
+ assert_conversion_find (src_img->type[0], dst_img->type[0]),
+ src_img, dst_img,
+ n);
+ src_img->data[0] += src_img->type[0]->bits/8;
+ }
+ babl_free (src_img);
+ babl_free (dst_img);
+}
+
+
+static void
+convert_from_double (BablFormat *destination_fmt,
+ void *destination_double_buf,
+ BablImage *destination,
+ void *destination_buf,
+ int n)
+{
+ int i;
+
+ BablImage *src_img;
+ BablImage *dst_img;
+
+ src_img = (BablImage*) babl_image (
+ babl_component_id (BABL_LUMINANCE), NULL, 1, 0, NULL);
+ dst_img = (BablImage*) babl_image (
+ babl_component_id (BABL_LUMINANCE), NULL, 1, 0, NULL);
+
+ src_img->type[0] = (BablType*) babl_type_id (BABL_DOUBLE);
+ src_img->pitch[0] = (src_img->type[0]->bits/8) * destination_fmt->model->components;
+ src_img->stride[0] = 0;
+
+ dst_img->data[0] = destination_buf;
+ dst_img->type[0] = (BablType*) babl_type_id (BABL_DOUBLE);
+ dst_img->pitch[0] = destination_fmt->bytes_per_pixel;
+ dst_img->stride = 0;
+
+ for (i=0 ; i<destination_fmt->components; i++)
+ {
+ int j;
+
+ dst_img->type[0] = destination_fmt->type[i];
+
+ for (j=0;j<destination_fmt->model->components;j++)
+ {
+ if (destination_fmt->component[i] ==
+ destination_fmt->model->component[j])
+ {
+ src_img->data[0] =
+ destination_double_buf + (src_img->type[0]->bits/8) * j;
+ break;
+ }
+ }
+
+ babl_process (
+ assert_conversion_find (src_img->type[0], dst_img->type[0]),
+ src_img, dst_img,
+ n);
+ dst_img->data[0] += dst_img->type[0]->bits/8;
+ }
+ babl_free (src_img);
+ babl_free (dst_img);
+}
+
+
+static int
+process_same_model (Babl *babl,
+ BablImage *source,
+ BablImage *destination,
+ long n)
+{
+ void *double_buf;
+
+ if (BABL_IS_BABL (source) ||
+ BABL_IS_BABL (destination))
+ {
+ babl_log ("args=(%p, %p, %p, %li): trying to handle BablImage (unconfirmed code)",
+ babl_fish, source, destination, n);
+ }
+
+ double_buf = babl_malloc(sizeof (double) * n *
+ BABL(babl->fish.source)->format.model->components);
+
+ convert_to_double (
+ (BablFormat*) BABL(babl->fish.source),
+ BABL_IS_BABL(source)?source:NULL,
+ BABL_IS_BABL(source)?NULL:source,
+ double_buf,
+ n
+ );
+
+ convert_from_double (
+ (BablFormat*) BABL(babl->fish.destination),
+ double_buf,
+ BABL_IS_BABL(destination)?destination:NULL,
+ BABL_IS_BABL(destination)?NULL:destination,
+ n
+ );
+
+ babl_free (double_buf);
+ return 0;
+}
+
+long
+babl_fish_reference_process (Babl *babl,
+ BablImage *source,
+ BablImage *destination,
+ long n)
+{
+ void *source_double_buf;
+ void *rgba_double_buf;
+ void *destination_double_buf;
+ Babl *source_image;
+ Babl *rgba_image;
+ Babl *destination_image;
+
+ if (BABL(babl->fish.source)->format.model ==
+ BABL(babl->fish.destination)->format.model)
+ return process_same_model (babl, source, destination, n);
+
+ if (BABL_IS_BABL (source) ||
+ BABL_IS_BABL (destination))
+ {
+ babl_log ("args=(%p, %p, %p, %li): trying to handle BablImage (unconfirmed code)",
+ babl_fish, source, destination, n);
+ }
+
+ source_double_buf = babl_malloc(sizeof (double) * n *
+ BABL(babl->fish.source)->format.model->components);
+ rgba_double_buf = babl_malloc(sizeof (double) * n * 4);
+ destination_double_buf = babl_malloc(sizeof (double) * n *
+ BABL(babl->fish.destination)->format.model->components);
+
+ source_image = babl_image_from_linear (
+ source_double_buf,BABL(BABL((babl->fish.source)) -> format.model));
+ rgba_image = babl_image_from_linear (
+ rgba_double_buf, babl_model_id (BABL_RGBA));
+ destination_image = babl_image_from_linear (
+ destination_double_buf, BABL(BABL((babl->fish.destination))->format.model));
+
+ convert_to_double (
+ (BablFormat*) BABL(babl->fish.source),
+ BABL_IS_BABL(source)?source:NULL,
+ BABL_IS_BABL(source)?NULL:source,
+ source_double_buf,
+ n
+ );
+
+ {
+ Babl *conv =
+ assert_conversion_find (
+ BABL(babl->fish.source)->format.model,
+ babl_model_id (BABL_RGBA)
+ );
+ if (conv->class_type == BABL_CONVERSION_PLANAR)
+ {
+ babl_process (
+ conv,
+ source_image, rgba_image,
+ n);
+ }
+ else if (conv->class_type == BABL_CONVERSION_LINEAR)
+ {
+ babl_process (
+ conv,
+ source_double_buf, rgba_double_buf,
+ n);
+ }
+ else babl_fatal ("oops");
+ }
+
+ {
+ Babl *conv =
+ assert_conversion_find (
+ babl_model_id (BABL_RGBA),
+ BABL(babl->fish.destination)->format.model);
+ if (conv->class_type == BABL_CONVERSION_PLANAR)
+ {
+ babl_process (
+ conv,
+ rgba_image, destination_image,
+ n);
+ }
+ else if (conv->class_type == BABL_CONVERSION_LINEAR)
+ {
+ babl_process (
+ conv,
+ rgba_double_buf, destination_double_buf,
+ n);
+ }
+ else babl_fatal ("oops");
+ }
+
+ convert_from_double (
+ (BablFormat*) BABL(babl->fish.destination),
+ destination_double_buf,
+ BABL_IS_BABL(destination)?destination:NULL,
+ BABL_IS_BABL(destination)?NULL:destination,
+ n
+ );
+
+ babl_free (source_image);
+ babl_free (rgba_image);
+ babl_free (destination_image);
+
+ babl_free (destination_double_buf);
+ babl_free (rgba_double_buf);
+ babl_free (source_double_buf);
+ return n;
+}
+
--- /dev/null
+/* babl - dynamically extendable universal pixel fish library.
+ * Copyright (C) 2005, Øyvind Kolås.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "babl-internal.h"
+
+static char *
+create_name (BablConversion *conversion)
+{
+ return conversion->instance.name;
+}
+
+Babl *
+babl_fish_simple (BablConversion *conversion)
+{
+ Babl *babl = NULL;
+ char *name;
+
+ babl_assert (BABL_IS_BABL (conversion));
+
+ name = create_name (conversion);
+
+ babl = babl_malloc (sizeof (BablFishSimple) +
+ strlen (name) + 1);
+ babl->class_type = BABL_FISH_SIMPLE;
+ babl->instance.id = 0;
+ babl->instance.name = ((void *)babl) + sizeof(BablFishSimple);
+ strcpy (babl->instance.name, name);
+ babl->fish.source = (union Babl*)conversion->source;
+ babl->fish.destination = (union Babl*)conversion->destination;
+
+ babl->fish.processings = 0;
+ babl->fish.pixels = 0;
+ babl->fish_simple.conversion = conversion;
+
+ {
+ Babl *ret = babl_db_insert (babl_fish_db (), babl);
+ if (ret!=babl)
+ babl_free (babl);
+ return ret;
+ }
+}
*/
#include "babl-internal.h"
-#include "babl-db.h"
#include <string.h>
#include <stdarg.h>
-/*#include "babl-type.h"
-#include "babl-model.h"
-#include "babl-image.h"
-#include "babl-component.h"
-#include "babl-format.h"*/
-static int
-each_babl_fish_destroy (Babl *babl,
- void *data)
-{
- babl_free (babl);
- return 0; /* continue iterating */
-}
-
-static char buf[1024];
-static char *
-create_name (Babl *source,
- Babl *destination,
- int is_reference)
-{
- /* fish names are intentionally kept short */
- snprintf (buf, 1024, "%s %p %p",
- is_reference?"ref "
- :"",
- source, destination);
- return buf;
-}
-
-typedef struct SearchData
-{
- Babl *source;
- Babl *destination;
- BablConversion *result;
-} SearchData;
-
-Babl *babl_conversion_find2 (void *source,
- void *destination)
-{
- int i=0;
- Babl **conversion;
-
- conversion = (void*)BABL(source)->type.from;
- while (conversion && conversion[i])
- {
- if (conversion[i]->conversion.destination == destination)
- return (Babl*)conversion[i];
- i++;
- }
- babl_fatal ("failed, aborting");
- return NULL;
-}
-
-
-Babl *babl_conversion_find (void *source,
- void *destination)
+static int
+match_conversion (Babl *conversion,
+ void *inout)
{
- int i=0;
- Babl **conversion;
+ void **data = inout;
- conversion = (void*)BABL(source)->type.from;
- while (conversion && conversion[i])
+ if ((Babl *) conversion->conversion.destination == (Babl*) *data)
{
- if (conversion[i]->conversion.destination == destination)
- return (Babl*)conversion[i];
- i++;
+ *data = (void *)conversion;
+ return 1;
}
- return NULL;
+ return 0;
}
-
-
Babl *
-babl_fish_reference (Babl *source,
- Babl *destination)
+babl_conversion_find (void *source,
+ void *destination)
{
- Babl *babl = NULL;
- char *name = create_name (source, destination, 1);
-
- babl_assert (BABL_IS_BABL (source));
- babl_assert (BABL_IS_BABL (destination));
-
- babl_assert (source->class_type == BABL_FORMAT);
- babl_assert (destination->class_type == BABL_FORMAT);
+ void *data=destination;
- babl = babl_malloc (sizeof (BablFishReference) +
- strlen (name) + 1);
- babl->class_type = BABL_FISH_REFERENCE;
- babl->instance.id = 0;
- babl->instance.name = ((void *)babl) + sizeof(BablFishReference);
- strcpy (babl->instance.name, name);
- babl->fish.source = (union Babl*)source;
- babl->fish.destination = (union Babl*)destination;
-
- babl->fish.processings = 0;
- babl->fish.pixels = 0;
-
- {
- Babl *ret = babl_db_insert (db, babl);
- if (ret!=babl)
- babl_free (babl);
- return ret;
- }
+ babl_list_each ((void*)BABL(source)->type.from, match_conversion, &data);
+ if (data == destination)
+ return NULL;
+ return data;
}
-Babl *
-babl_fish_simple (BablConversion *conversion)
+BablDb *
+babl_fish_db (void)
{
- Babl *babl = NULL;
- char *name;
-
- babl_assert (BABL_IS_BABL (conversion));
-
- name = create_name (BABL(conversion->source),
- BABL(conversion->destination),
- 0);
-
- babl = babl_malloc (sizeof (BablFishSimple) +
- strlen (name) + 1);
- babl->class_type = BABL_FISH_SIMPLE;
- babl->instance.id = 0;
- babl->instance.name = ((void *)babl) + sizeof(BablFishSimple);
- strcpy (babl->instance.name, name);
- babl->fish.source = (union Babl*)conversion->source;
- babl->fish.destination = (union Babl*)conversion->destination;
-
- babl->fish.processings = 0;
- babl->fish.pixels = 0;
- babl->fish_simple.conversion = conversion;
-
- {
- Babl *ret = babl_db_insert (db, babl);
- if (ret!=babl)
- babl_free (babl);
- return ret;
- }
+ if (!db)
+ db = babl_db_init ();
+ return db;
}
Babl *
babl_fish (void *source,
- void *destination)
+ void *destination,
+ ...)
{
Babl *source_format = NULL;
Babl *destination_format = NULL;
}
- {
- Babl *shortcut_conversion = babl_conversion_find (source_format, destination_format);
+ if (0)
+ {
+ Babl *shortcut_conversion;
+
+ shortcut_conversion = babl_conversion_find (
+ source_format, destination_format);
if (shortcut_conversion)
{
return babl_fish_simple (&(shortcut_conversion->conversion));
}
}
- return babl_fish_reference (source_format, destination_format);
-}
-
-
-static void
-convert_to_double (BablFormat *source_fmt,
- BablImage *source,
- void *source_buf,
- void *source_double_buf,
- int n)
-{
- int i;
-
- BablImage *src_img;
- BablImage *dst_img;
-
- src_img = (BablImage*) babl_image (
- babl_component_id (BABL_LUMINANCE), NULL, 1, 0, NULL);
- dst_img = (BablImage*) babl_image (
- babl_component_id (BABL_LUMINANCE), NULL, 1, 0, NULL);
-
- dst_img->type[0] = (BablType*) babl_type_id (BABL_DOUBLE);
- dst_img->pitch[0] =
- (dst_img->type[0]->bits/8) * source_fmt->model->components;
- dst_img->stride[0] = 0;
-
-
- src_img->data[0] = source_buf;
- src_img->type[0] = (BablType*) babl_type_id (BABL_DOUBLE);
- src_img->pitch[0] = source_fmt->bytes_per_pixel;
- src_img->stride[0] = 0;
-
- /* i is source position */
- for (i=0 ; i<source_fmt->components; i++)
- {
- int j;
-
- src_img->type[0] = source_fmt->type[i];
- /* j is source position */
- for (j=0;j<source_fmt->model->components;j++)
- {
- if (source_fmt->component[i] ==
- source_fmt->model->component[j])
- {
- dst_img->data[0] =
- source_double_buf + (dst_img->type[0]->bits/8) * j;
- break;
- }
- }
-
- babl_process (
- babl_conversion_find2 (src_img->type[0], dst_img->type[0]),
- src_img, dst_img,
- n);
- src_img->data[0] += src_img->type[0]->bits/8;
- }
- babl_free (src_img);
- babl_free (dst_img);
-}
-
-
-static void
-convert_from_double (BablFormat *destination_fmt,
- void *destination_double_buf,
- BablImage *destination,
- void *destination_buf,
- int n)
-{
- int i;
-
- BablImage *src_img;
- BablImage *dst_img;
-
- src_img = (BablImage*) babl_image (
- babl_component_id (BABL_LUMINANCE), NULL, 1, 0, NULL);
- dst_img = (BablImage*) babl_image (
- babl_component_id (BABL_LUMINANCE), NULL, 1, 0, NULL);
-
- src_img->type[0] = (BablType*) babl_type_id (BABL_DOUBLE);
- src_img->pitch[0] =
- (src_img->type[0]->bits/8) * destination_fmt->model->components;
- src_img->stride[0] = 0;
-
- dst_img->data[0] = destination_buf;
- dst_img->type[0] = (BablType*) babl_type_id (BABL_DOUBLE);
- dst_img->pitch[0] = destination_fmt->bytes_per_pixel;
- dst_img->stride = 0;
-
- for (i=0 ; i<destination_fmt->components; i++)
- {
- int j;
-
- dst_img->type[0] = destination_fmt->type[i];
-
- for (j=0;j<destination_fmt->model->components;j++)
- {
- if (destination_fmt->component[i] ==
- destination_fmt->model->component[j])
- {
- src_img->data[0] =
- destination_double_buf + (src_img->type[0]->bits/8) * j;
- break;
- }
- }
- babl_process (
- babl_conversion_find2 (src_img->type[0], dst_img->type[0]),
- src_img, dst_img,
- n);
- dst_img->data[0] += dst_img->type[0]->bits/8;
- }
- babl_free (src_img);
- babl_free (dst_img);
-}
+ {
+ Babl *fish_path;
+
+ fish_path = babl_fish_path (source_format, destination_format);
-static int
-process_same_model (Babl *babl,
- BablImage *source,
- BablImage *destination,
- long n)
-{
- void *double_buf;
-
- if (BABL_IS_BABL (source) ||
- BABL_IS_BABL (destination))
- {
- babl_log ("args=(%p, %p, %p, %li): trying to handle BablImage (unconfirmed code)",
- babl_fish, source, destination, n);
- }
-
- double_buf = babl_malloc(sizeof (double) * n *
- BABL(babl->fish.source)->format.model->components);
-
- convert_to_double (
- (BablFormat*) BABL(babl->fish.source),
- BABL_IS_BABL(source)?source:NULL,
- BABL_IS_BABL(source)?NULL:source,
- double_buf,
- n
- );
-
- convert_from_double (
- (BablFormat*) BABL(babl->fish.destination),
- double_buf,
- BABL_IS_BABL(destination)?destination:NULL,
- BABL_IS_BABL(destination)?NULL:destination,
- n
- );
+ if (fish_path)
+ {
+ return fish_path;
+ }
+ }
- babl_free (double_buf);
- return 0;
+ return babl_fish_reference (source_format, destination_format);
}
-int
-babl_fish_reference_process (Babl *babl,
- BablImage *source,
- BablImage *destination,
- long n)
+long
+babl_fish_process (Babl *babl,
+ void *source,
+ void *destination,
+ long n)
{
- void *source_double_buf;
- void *rgba_double_buf;
- void *destination_double_buf;
- Babl *source_image;
- Babl *rgba_image;
- Babl *destination_image;
+ BablImage *source_image = NULL;
+ BablImage *destination_image = NULL;
+ long ret=0;
- if (BABL(babl->fish.source)->format.model ==
- BABL(babl->fish.destination)->format.model)
- return process_same_model (babl, source, destination, n);
-
- if (BABL_IS_BABL (source) ||
- BABL_IS_BABL (destination))
+ switch (babl->class_type)
{
- babl_log ("args=(%p, %p, %p, %li): trying to handle BablImage (unconfirmed code)",
- babl_fish, source, destination, n);
+ case BABL_FISH_REFERENCE:
+ case BABL_FISH_SIMPLE:
+ case BABL_FISH_PATH:
+
+ if (BABL_IS_BABL (source))
+ source_image = source;
+ if (!source_image)
+ source_image = (BablImage*) babl_image_from_linear (
+ source, (Babl*)babl->fish.source);
+ if (BABL_IS_BABL (destination))
+ destination_image = destination;
+ if (!destination_image)
+ destination_image = (BablImage*) babl_image_from_linear (
+ destination, (Babl*)babl->fish.destination);
+
+ if (babl->class_type == BABL_FISH_REFERENCE)
+ {
+ ret = babl_fish_reference_process (babl, source, destination, n);
+ }
+ else if (babl->class_type == BABL_FISH_PATH)
+ {
+ ret = babl_fish_path_process (babl, source, destination, n);
+ }
+ else if (babl->class_type == BABL_FISH_SIMPLE)
+ {
+ if (BABL(babl->fish_simple.conversion)->class_type==BABL_CONVERSION_LINEAR)
+ {
+ ret = babl_conversion_process (BABL(babl->fish_simple.conversion),
+ source, destination, n);
+ }
+ else
+ {
+ ret = babl_conversion_process (BABL(babl->fish_simple.conversion),
+ source_image, destination_image, n);
+ }
+ }
+
+ babl_free (source_image);
+ babl_free (destination_image);
+ break;
+ default:
+ babl_log ("NYI");
+ ret = -1;
+ break;
}
- source_double_buf = babl_malloc(sizeof (double) * n *
- BABL(babl->fish.source)->format.model->components);
- rgba_double_buf = babl_malloc(sizeof (double) * n * 4);
- destination_double_buf = babl_malloc(sizeof (double) * n *
- BABL(babl->fish.destination)->format.model->components);
-
- source_image = babl_image_from_linear (
- source_double_buf,BABL(BABL((babl->fish.source)) -> format.model));
- rgba_image = babl_image_from_linear (
- rgba_double_buf, babl_model_id (BABL_RGBA));
- destination_image = babl_image_from_linear (
- destination_double_buf, BABL(BABL((babl->fish.destination))->format.model));
-
- convert_to_double (
- (BablFormat*) BABL(babl->fish.source),
- BABL_IS_BABL(source)?source:NULL,
- BABL_IS_BABL(source)?NULL:source,
- source_double_buf,
- n
- );
-
- babl_process (
- babl_conversion_find2 (
- BABL(babl->fish.source)->format.model,
- babl_model_id (BABL_RGBA)
- ),
- source_image, rgba_image,
- n);
-
- babl_process (
- babl_conversion_find2 (
- babl_model_id (BABL_RGBA),
- BABL(babl->fish.destination)->format.model
- ),
- rgba_image, destination_image,
- n);
-
- convert_from_double (
- (BablFormat*) BABL(babl->fish.destination),
- destination_double_buf,
- BABL_IS_BABL(destination)?destination:NULL,
- BABL_IS_BABL(destination)?NULL:destination,
- n
- );
-
- babl_free (source_image);
- babl_free (rgba_image);
- babl_free (destination_image);
-
- babl_free (destination_double_buf);
- babl_free (rgba_double_buf);
- babl_free (source_double_buf);
- return 0;
+ return ret;
}
-int
-babl_fish_process (Babl *babl,
- void *source,
- void *destination,
- long n)
+static int
+each_babl_fish_destroy (Babl *babl,
+ void *data)
{
- babl_log ("NYI");
- return -1;
+ babl_free (babl);
+ return 0; /* continue iterating */
}
-
-
BABL_DEFINE_INIT (fish)
BABL_DEFINE_DESTROY (fish)
BABL_DEFINE_EACH (fish)
#include <string.h>
#include <stdarg.h>
+#include <math.h>
#include "babl-internal.h"
#include "babl-db.h"
BablType *type [BABL_MAX_COMPONENTS];
BablSampling *current_sampling = (BablSampling*) babl_sampling (1,1);
- BablType *current_type = (BablType*) babl_type_id (BABL_U8);
+ BablType *current_type = (BablType*) babl_type_id (BABL_DOUBLE);
char *name = NULL;
void *arg = first_arg;
case BABL_CONVERSION_PLANE:
case BABL_CONVERSION_PLANAR:
case BABL_FISH:
- case BABL_FISH_SIMPLE:
case BABL_FISH_REFERENCE:
+ case BABL_FISH_SIMPLE:
+ case BABL_FISH_PATH:
case BABL_IMAGE:
case BABL_EXTENSION:
babl_log ("%s unexpected",
}
}
+int
+babl_formats_count (void)
+{
+ return babl_db_count (db);
+}
+
+
+Babl *
+babl_format_with_model_as_type (Babl *model,
+ Babl *type)
+{
+ BablComponent *component[10];
+ int i;
+
+ for (i=0;i<model->model.components;i++)
+ {
+ component[i]= model->model.component[i];
+ }
+ component[i]=NULL;
+
+ return babl_format_new (
+ model,
+ type,
+ component[0],
+ component[1],
+ component[2],
+ component[3],
+ component[4],
+ component[5],
+ component[6],
+ component[7],
+ component[8],
+ component[9],
+ NULL
+ );
+}
+
+#define pixels 256
+
+static double *
+test_create (void)
+{
+ double *test;
+ int i;
+
+ srandom (20050728);
+
+ test = babl_malloc (sizeof (double) * pixels * 4);
+
+ for (i = 0; i < pixels * 4; i++)
+ test [i] = (double) random () / RAND_MAX;
+
+ return test;
+}
+
+double
+babl_format_loss (Babl *babl)
+{
+ double loss = 0.0;
+ double *test;
+ void *original;
+ double *clipped;
+ void *destination;
+ double *transformed;
+
+ Babl *ref_fmt;
+ Babl *fmt;
+ Babl *fish_to;
+ Babl *fish_from;
+
+ ref_fmt = babl_format_new (
+ babl_model ("RGBA"),
+ babl_type ("double"),
+ babl_component ("R"),
+ babl_component ("G"),
+ babl_component ("B"),
+ babl_component ("A"),
+ NULL);
+
+ if (babl->format.loss != -1.0)
+ return babl->format.loss;
+
+ fmt = babl;
+ fish_to = babl_fish_reference (ref_fmt, fmt);
+ fish_from = babl_fish_reference (fmt, ref_fmt);
+
+ test = test_create ();
+ original = babl_calloc (pixels, fmt->format.bytes_per_pixel);
+ clipped = babl_calloc (pixels, ref_fmt->format.bytes_per_pixel);
+ destination = babl_calloc (pixels, fmt->format.bytes_per_pixel);
+ transformed = babl_calloc (pixels, ref_fmt->format.bytes_per_pixel);
+
+ babl_process (fish_to, test, original, pixels);
+ babl_process (fish_from, original, clipped, pixels);
+ babl_process (fish_to, clipped, destination, pixels);
+ babl_process (fish_from, destination, transformed, pixels);
+
+ {
+ int i;
+
+ for (i=0;i<pixels*4;i++)
+ {
+ loss += fabs (clipped[i] - test[i]);
+ }
+ loss /= pixels;
+
+ }
+
+ babl_free (original);
+ babl_free (clipped);
+ babl_free (destination);
+ babl_free (transformed);
+ babl_free (test);
+
+ babl->format.loss = loss;
+ return loss;
+}
+
BABL_CLASS_TEMPLATE (format)
"BablFish",
"BablFishReference",
"BablFishSimple",
+ "BablFishPath",
"BablImage",
"BablExtenstion",
"BablSky"
exit (-1);
}
-long babl_conversion_process (Babl *conversion,
- void *source,
- void *destination,
- long n);
long
babl_process (Babl *babl,
void *source,
babl_assert (BABL_IS_BABL (babl));
babl_assert (n>0);
- /* these fields are common between conversions and fishes */
- babl->fish.processings++;
- babl->fish.pixels += n;
-
/* matches all conversion classes */
if (babl->class_type >= BABL_CONVERSION &&
babl->class_type <= BABL_CONVERSION_PLANAR)
return babl_conversion_process (babl, source, destination, n);
- if (babl->class_type == BABL_FISH)
- return babl_fish_process (babl, source, destination, n);
-
- if (babl->class_type == BABL_FISH_REFERENCE)
- {
- BablImage *source_image = NULL;
- BablImage *destination_image = NULL;
- long ret=0;
-
- if (BABL_IS_BABL (source))
- source_image = source;
- if (!source_image)
- source_image = (BablImage*) babl_image_from_linear (
- source, (Babl*)babl->fish.source);
- if (BABL_IS_BABL (destination))
- destination_image = destination;
- if (!destination_image)
- destination_image = (BablImage*) babl_image_from_linear (
- destination, (Babl*)babl->fish.destination);
-
- ret = babl_fish_reference_process (babl, source, destination, n);
-
- babl_free (source_image);
- babl_free (destination_image);
-
- return ret;
- }
-
- if (babl->class_type == BABL_FISH_SIMPLE)
+ if (babl->class_type == BABL_FISH ||
+ babl->class_type == BABL_FISH_REFERENCE ||
+ babl->class_type == BABL_FISH_PATH ||
+ babl->class_type == BABL_FISH_SIMPLE)
{
- long ret=0;
- BablImage *source_image = NULL;
- BablImage *destination_image = NULL;
-
- if (BABL_IS_BABL (source))
- source_image = source;
- if (!source_image)
- source_image = (BablImage*) babl_image_from_linear (
- source, (Babl*)babl->fish.source);
- if (BABL_IS_BABL (destination))
- destination_image = destination;
- if (!destination_image)
- destination_image = (BablImage*) babl_image_from_linear (
- destination, (Babl*)babl->fish.destination);
-
- if (BABL(babl->fish_simple.conversion)->class_type==BABL_CONVERSION_LINEAR)
- {
- ret = babl_conversion_process (BABL(babl->fish_simple.conversion),
- source, destination, n);
- }
- else
- {
- ret = babl_conversion_process (BABL(babl->fish_simple.conversion),
- source_image, destination_image, n);
- }
-
- babl_free (source_image);
- babl_free (destination_image);
-
- return ret;
+ babl->fish.processings++;
+ babl->fish.pixels += n;
+ return babl_fish_process (babl, source, destination, n);
}
- babl_log ("eek");
+ babl_fatal ("eek");
return -1;
}
babl_assert (BABL_IS_BABL (babl));
return babl->instance.name;
}
+
+static int
+each_conversion (Babl *babl,
+ void *user_data)
+{
+ babl_conversion_error (&babl->conversion);
+ return 0;
+}
+
+static int
+each_format (Babl *babl,
+ void *user_data)
+{
+ babl_format_loss (babl);
+ return 0;
+}
+
+static int
+gen_type_format_for_model (Babl *type, void *userdata)
+{
+ babl_format_with_model_as_type (userdata, type);
+ return 0;
+}
+
+static int
+gen_formats_for_model (Babl *model, void *userdata)
+{
+ babl_type_each (gen_type_format_for_model, model);
+ return 0;
+}
+
+void
+babl_extension_post_load (void)
+{
+ babl_conversion_each (each_conversion, NULL);
+ babl_format_each (each_format, NULL);
+ babl_model_each (gen_formats_for_model, NULL);
+}
+
#error babl-internal.h included after babl.h
#endif
-#define BABL_MAX_COMPONENTS 32
+#define BABL_MAX_COMPONENTS 32
+#define BABL_MAX_PATH_LENGTH 5
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "assert.h"
+
#include "babl-classes.h"
#undef _BABL_INTERNAL_H
#include "babl.h"
#include "babl-memory.h"
-int babl_fish_process (Babl *babl,
- void *source,
- void *destination,
- long n);
-int babl_fish_reference_process (Babl *babl,
- BablImage *source,
- BablImage *destination,
- long n);
-Babl * babl_fish_reference (Babl *source,
- Babl *destination);
-Babl * babl_fish_simple (BablConversion *conversion);
-Babl * babl_image_from_linear (void *buffer,
- Babl *format);
-Babl * babl_image_double_from_image (Babl *source);
-void babl_die (void);
-int babl_sanity (void);
-Babl * babl_extension_base (void);
-
-Babl * babl_extender (void);
-void babl_set_extender (Babl *new_extender);
-
-Babl * babl_extension_quiet_log (void);
-
-void babl_core_init (void);
+Babl * babl_conversion_find (void *source,
+ void *destination);
+double babl_conversion_error (BablConversion *conversion);
+long babl_conversion_process (Babl *conversion,
+ void *source,
+ void *destination,
+ long n);
+
+Babl * babl_extension_base (void);
+void babl_extension_post_load (void);
+
+Babl * babl_extender (void);
+void babl_set_extender (Babl *new_extender);
+
+Babl * babl_extension_quiet_log (void);
+
+long babl_fish_process (Babl *babl,
+ void *source,
+ void *destination,
+ long n);
+long babl_fish_reference_process (Babl *babl,
+ BablImage *source,
+ BablImage *destination,
+ long n);
+
+BablDb * babl_fish_db (void);
+Babl * babl_fish_reference (Babl *source,
+ Babl *destination);
+Babl * babl_fish_simple (BablConversion *conversion);
+Babl * babl_fish_path (Babl *source,
+ Babl *destination);
+
+long babl_fish_path_process (Babl *babl,
+ void *source,
+ void *destination,
+ long n);
+
+double babl_format_loss (Babl *babl);
+Babl * babl_image_from_linear (void *buffer,
+ Babl *format);
+Babl * babl_image_double_from_image (Babl *source);
+
+double babl_model_is_symmetric (Babl *babl);
+void babl_die (void);
+int babl_sanity (void);
+
+void babl_core_init (void);
+Babl * babl_format_with_model_as_type (Babl *model,
+ Babl *type);
+int babl_formats_count (void); /* should maybe be templated? */
+int babl_type_is_symmetric (Babl *babl);
/* FIXME: nasty,. including the symbol even in files where it is
* not needed,. and a dummy function to use it in those cases
va_end (varg);
fprintf (stdout, "\n");
+ fflush (0);
return;
hack_hack ();
}
babl = babl_db_exist (db, id, NULL); \
if (!babl) \
{ \
- babl_log ("%s(%i): not found", __FUNCTION__, id); \
+ babl_fatal ("%s(%i): not found", __FUNCTION__, id); \
} \
return babl; \
}
{
babl_log ("\t\tprocessings:%i pixels:%li",
babl->conversion.processings, babl->conversion.pixels);
+ babl_log ("\t\tcost: %i error: %f", babl->conversion.cost, babl->conversion.error);
}
static void
#include "babl-internal.h"
#include <string.h>
#include <stdarg.h>
+#include <math.h>
#include "babl-db.h"
case BABL_CONVERSION_PLANE:
case BABL_CONVERSION_PLANAR:
case BABL_FISH:
- case BABL_FISH_REFERENCE:
case BABL_FISH_SIMPLE:
+ case BABL_FISH_REFERENCE:
+ case BABL_FISH_PATH:
case BABL_IMAGE:
case BABL_EXTENSION:
babl_log ("%s unexpected", babl_class_name (babl->class_type));
}
}
+
+#define TOLERANCE 0.001
+
+#define pixels 512
+
+static double *
+test_create (void)
+{
+ double *test;
+ int i;
+
+ srandom (20050728);
+
+ test = babl_malloc (sizeof (double) * pixels * 4);
+
+ for (i = 0; i < pixels * 4; i++)
+ test [i] = ((double) random () / RAND_MAX ) * 1.4 - 0.2;
+
+ return test;
+}
+
+static Babl *reference_format (void)
+{
+ static Babl *self = NULL;
+
+ if (!self)
+ self = babl_format_new (
+ babl_model ("RGBA"),
+ babl_type ("double"),
+ babl_component ("R"),
+ babl_component ("G"),
+ babl_component ("B"),
+ babl_component ("A"),
+ NULL);
+ return self;
+}
+
+static Babl *construct_double_format (Babl *model)
+{
+ void *argument[42+1];
+ int args = 0;
+ int i;
+
+ argument[args++] = model;
+ argument[args++] = babl_type ("double");
+
+ for (i=0;i<model->model.components; i++)
+ {
+ argument[args++] = model->model.component[i];
+ }
+ argument[args++] = NULL;
+
+#define o(argno) argument[argno],
+ return babl_format_new (o(0) o(1) o(2) o(3)
+ o(4) o(5) o(6) o(7)
+ o(8) o(9) o(10) o(11)
+ o(12) o(13) o(14) o(15)
+ o(16) o(17) o(18) o(19)
+ o(20) o(21) o(22) o(23)
+ o(24) o(25) o(26) o(27)
+ o(28) o(29) o(30) o(31)
+ o(32) o(33) o(34) o(35)
+ o(36) o(37) o(38) o(39)
+ o(40) o(41) o(42) NULL);
+#undef o
+}
+
+double
+babl_model_is_symmetric (Babl *babl)
+{
+ double *test;
+ void *original;
+ double *clipped;
+ void *destination;
+ double *transformed;
+ int symmetric=1;
+
+ Babl *ref_fmt;
+ Babl *fmt;
+ Babl *fish_to;
+ Babl *fish_from;
+
+ test = test_create ();
+ ref_fmt = reference_format ();
+ fmt = construct_double_format (babl);
+ fish_to = babl_fish_reference (ref_fmt, fmt);
+ fish_from = babl_fish_reference (fmt, ref_fmt);
+
+ original = babl_calloc (1,64/8 * babl->model.components * pixels);
+ clipped = babl_calloc (1,64/8 * 4 * pixels);
+ destination = babl_calloc (1,64/8 * babl->model.components * pixels);
+ transformed = babl_calloc (1,64/8 * 4 * pixels);
+
+ babl_process (fish_to, test, original, pixels);
+ babl_process (fish_from, original, clipped, pixels);
+ babl_process (fish_to, clipped, destination, pixels);
+ babl_process (fish_from, destination, transformed, pixels);
+
+ {
+ int i;
+ int log=0;
+
+ for (i=0;i<pixels;i++)
+ {
+ int j;
+ for (j=0;j<4;j++)
+ if (fabs (clipped[i*4+j] - transformed[i*4+j])>TOLERANCE)
+ {
+ if (!log)
+ log=1;
+ symmetric=0;
+ }
+ if (log && log < 5)
+ {
+ babl_log ("%s", babl->instance.name);
+ babl_log ("\ttest: %2.3f %2.3f %2.3f %2.3f", test [i*4+0],
+ test [i*4+1],
+ test [i*4+2],
+ test [i*4+3]);
+ babl_log ("\tclipped: %2.3f %2.3f %2.3f %2.3f", clipped [i*4+0],
+ clipped [i*4+1],
+ clipped [i*4+2],
+ clipped [i*4+3]);
+ babl_log ("\ttrnsfrmd: %2.3f %2.3f %2.3f %2.3f", transformed [i*4+0],
+ transformed [i*4+1],
+ transformed [i*4+2],
+ transformed [i*4+3]);
+ log++;
+ }
+ }
+ }
+
+ babl_free (original);
+ babl_free (clipped);
+ babl_free (destination);
+ babl_free (transformed);
+ babl_free (test);
+ return symmetric;
+}
+
BABL_CLASS_TEMPLATE (model)
id_sanity (Babl *babl,
void *user_data)
{
- if (0 == babl->instance.id &&
+ if (0 && 0 == babl->instance.id &&
babl->instance.creator &&
!strcmp(BABL(babl->instance.creator)->instance.name, "BablBase"))
{
#include <string.h>
#include <stdarg.h>
+#include <math.h>
#include "babl-internal.h"
#include "babl-db.h"
}
}
+
+#define TOLERANCE 0.000000001
+#define samples 512
+
+double test[samples];
+
+double r_interval (double min, double max)
+{
+ long int rand_i = random ();
+ double ret;
+ ret = (double) rand_i / RAND_MAX;
+ ret*=(max-min);
+ ret+=min;
+ return ret;
+}
+
+void test_init (double min, double max)
+{
+ int i;
+ srandom (20050728);
+ for (i=0;i<samples;i++)
+ {
+ test [i]=r_interval(min,max);
+ }
+}
+
+
+static Babl *double_vector_format (void)
+{
+ static Babl *self = NULL;
+
+ if (!self)
+ self = babl_format_new (
+ babl_model ("Y"),
+ babl_type ("double"),
+ babl_component ("Y"),
+ NULL);
+ return self;
+}
+
+int
+babl_type_is_symmetric (Babl *babl)
+{
+ int is_symmetrical=1;
+ void *original;
+ double *clipped;
+ void *destination;
+ double *transformed;
+
+ Babl *ref_fmt;
+ Babl *fmt;
+ Babl *fish_to;
+ Babl *fish_from;
+
+ test_init (0.0, 182.0);
+
+ ref_fmt = double_vector_format ();
+ fmt = babl_format_new (babl_model ("Y"),
+ babl,
+ babl_component ("Y"),
+ NULL);
+ fish_to = babl_fish_reference (ref_fmt, fmt);
+ fish_from = babl_fish_reference (fmt, ref_fmt);
+
+ original = babl_calloc (1,babl->type.bits/8 * samples);
+ clipped = babl_calloc (1,64/8 * samples);
+ destination = babl_calloc (1,babl->type.bits/8 * samples);
+ transformed = babl_calloc (1,64/8 * samples);
+
+ babl_process (fish_to, test, original, samples);
+ babl_process (fish_from, original, clipped, samples);
+ babl_process (fish_to, clipped, destination, samples);
+ babl_process (fish_from, destination, transformed, samples);
+
+ {
+ int cnt=0;
+ int i;
+ for (i=0;i<samples;i++)
+ {
+ if (fabs (clipped[i] - transformed[i])> TOLERANCE)
+ {
+ if (cnt++<4)
+ babl_log ("%s: %f %f %f)",
+ babl->instance.name, test[i], clipped[i], transformed[i]
+ );
+ is_symmetrical=0;
+ }
+ }
+ }
+
+ babl_free (original);
+ babl_free (clipped);
+ babl_free (destination);
+ babl_free (transformed);
+
+ return is_symmetrical;
+}
+
BABL_CLASS_TEMPLATE (type)